package com.h3bpm.web.controller;

import OThinker.Common.Data.BoolMatchValue;
import OThinker.Common.Organization.Models.User;
import OThinker.Common.charset.H3Charset;
import OThinker.H3.Controller.ControllerBase;
import OThinker.H3.Controller.RestfulApi.cloudpivot.ResponseResult;
import OThinker.H3.Entity.Data.Attachment.Attachment;
import OThinker.H3.Entity.Data.Attachment.AttachmentHeader;
import OThinker.H3.Entity.IEngine;
import OThinker.H3.Entity.Instance.Data.InstanceData;
import OThinker.H3.Entity.Tracking.UserLog;
import OThinker.H3.Entity.Tracking.UserLogType;
import com.h3bpm.base.user.UserValidator;
import com.h3bpm.base.util.CharsetUtil;
import com.h3bpm.base.util.SheetUtility;
import com.h3bpm.web.utils.StatementUntil;
import net.sf.json.JSONObject;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author zhengyj
 * @date 2019/10/11
 * @description NTKO有关文件类控制器
 */
@Controller
@RequestMapping("/Portal/ntko/file")
public class NtkoController extends ControllerBase {

    private static final Logger LOGGER = LoggerFactory.getLogger(NtkoController.class);
    public final String folderPath = "/Portal/TempImages/storage/";

    private ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);

    @Override
    public String getFunctionCode() {
        return null;
    }

    @RequestMapping(value = "/getAttachmentUrl",method={RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public final Object Read(String BizObjectSchemaCode, String BizObjectID, String attachmentId)  {
        System.out.println("..........Read1");
        UserLog log;
        Attachment attachment = null;
        try {
            attachment = getEngine().getBizObjectManager().GetAttachment(this.getUserValidator().getUserID(), BizObjectSchemaCode, BizObjectID, attachmentId);

        log = new UserLog(UserLogType.OpenAttachment, this.getUserValidator().getUserID(), attachment.getBizObjectSchemaCode(), attachment.getBizObjectId(), attachment.getBizObjectId(), "", attachment.getFileName(), null, SheetUtility.GetClientIP(this.request), SheetUtility.GetClientPlatform(this.request), SheetUtility.GetClientBrowser(this.request));
        getEngine().getUserLogWriter().Write(log);
        String fileName = System.currentTimeMillis() + attachment.getFileName();
        System.out.println("....read...write...fileName:" + fileName);
        //update by luwei : app
        String realPath = request.getSession().getServletContext().getRealPath("/");
        System.out.println("realPath :    " + realPath);
        // 20190508 add by ousf 判断临时文件夹是否存在，不存在则创建 ------
        String dirPath = realPath + folderPath;
        System.out.println("dirPath :    " + dirPath);
        File dir = new File(dirPath);
        if(!dir.exists()&&!dir.isDirectory()){
            System.out.println("....read...write...create directory:" + dir);
            dir.mkdirs();
        }
        String savePath = dirPath + fileName;
        String viewUrl = folderPath + fileName;

        File f = new File(savePath);
        FileOutputStream fs = new FileOutputStream(f);
        fs.write(attachment.getContent());
        fs.close();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("url", viewUrl);
        jsonObject.put("filename", fileName);
        jsonObject.put("extension", fileName.substring(fileName.lastIndexOf(".") + 1));
        jsonObject.put("success", true);

        return jsonObject;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping(value = "/getAttachmentUrl2",method={RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public final Object Read2(String BizObjectSchemaCode, String BizObjectID, String attachmentId) throws Exception {

        Attachment attachment = getEngine().getBizObjectManager().GetAttachment(this.getUserValidator().getUserID(), BizObjectSchemaCode, BizObjectID, attachmentId);
        LOGGER.info("-----------------------  Read Attachment success   -----------------");
        return attachment.getContent();
    }


    @RequestMapping(value = "/ReadExcel",method={RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public final Object ReadExcel() throws Exception {
        XSSFWorkbook sheets = StatementUntil.generateExcel();
        String s = StatementUntil.PROJECT_PATH + StatementUntil.RESOURCES_PATH + StatementUntil.CONTRACT_STATEMENT_NAME;
        System.out.println("....read...write...fileName:" + StatementUntil.CONTRACT_STATEMENT_NAME);
        //update by luwei : app
        String realPath = request.getSession().getServletContext().getRealPath("/");

        // 20190508 add by ousf 判断临时文件夹是否存在，不存在则创建 ------
        String dirPath = realPath + folderPath;
        File dir = new File(dirPath);
        if(!dir.exists()&&!dir.isDirectory()){
            dir.mkdirs();
        }
        String filename = System.currentTimeMillis() + StatementUntil.CONTRACT_STATEMENT_NAME;
        String savePath = dirPath + filename;
        String viewUrl = folderPath +filename;
        File f = new File(savePath);
        FileOutputStream fs = new FileOutputStream(f);
        sheets.write(fs);
        fs.close();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("url", viewUrl);
        jsonObject.put("filename", filename);
        jsonObject.put("extension", filename.substring(StatementUntil.CONTRACT_STATEMENT_NAME.lastIndexOf(".") + 1));
        jsonObject.put("success", true);

        return jsonObject;
    }
    @RequestMapping(value = "/deleteFile",method={RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public final String deleteFile(String fileName) {
        String realPath = request.getSession().getServletContext().getRealPath("/");
        //删除临时文件
        String dirPath = realPath + folderPath;
        File file = new File(dirPath + fileName);
        if(file != null){
            file.delete();
            LOGGER.info("******  file be delete success   *******");
        }
        return "success";
    }

    @RequestMapping(value = "/updateFileTwo", method={RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public boolean updateFileTwo(String bizObjectSchemaCode, String bizObjectId, String attachmentID,@RequestParam("fileToUpload") MultipartFile fileToUpload) {
        InputStream stream = null;
        UserValidator uv=null;
        boolean bool;
        try {
            stream = fileToUpload.getInputStream();
            uv = getUserValidator();
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            RequestContextHolder.setRequestAttributes(servletRequestAttributes,true);
            bool = fileToUpload.getOriginalFilename().endsWith(".txt");
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        UserValidator finalUv = uv;
        InputStream finalStream = stream;
        fixedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    boolean b = saveToURL(bizObjectSchemaCode, bizObjectId, attachmentID, finalUv, finalStream,bool);
                    LOGGER.info(" update  file  is  :  " + b);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });

        return true;
    }

    public boolean saveToURL(String bizObjectSchemaCode, String bizObjectId, String attachmentID,UserValidator uv,InputStream stream,boolean bool)throws Exception{
        LOGGER.info("*************  start save file ,{},{},{}", bizObjectSchemaCode, bizObjectId, attachmentID);
        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        byte[] b_array = new byte[1024];


        String charset = CharsetUtil.getCharset(stream);

        int i=0;
        while((i=stream.read(b_array, 0, 1024))>0){
            baout.write(b_array, 0, i);
        }
        byte[] contents = baout.toByteArray();

        if (bool) {
            contents = new String(contents, charset).getBytes(H3Charset.DEFAULT_CHARSET);
        }
        //文件流
        if(contents != null){
            IEngine engine = this.getEngine();
            User user = engine.getOrganization().GetUserByCode("Administrator");
            Attachment attachment = engine.getBizObjectManager().GetAttachment(user.getObjectID(), bizObjectSchemaCode, bizObjectId, attachmentID);
            if(attachment != null){
                attachment.setContent(contents);

                String modifiedBy = uv == null ? user.getObjectID() : uv.getUserID();
                //更新文件
                engine.getBizObjectManager().UpdateAttachment(bizObjectSchemaCode, bizObjectId, attachmentID, modifiedBy, attachment.getFileName(), attachment.getContentType(), contents, attachment.getFileFlag());
                LOGGER.info("*************  file be update success   *************");
                return true;
            }
        }else {
            return false;
        }

        return false;
    }


    @RequestMapping(value = "/updateFile", method=RequestMethod.POST)
    @ResponseBody
    public boolean updateFile(String bizObjectSchemaCode, String bizObjectId, String attachmentID,@RequestParam("fileToUpload") MultipartFile fileToUpload)throws Exception {
        LOGGER.info("*************  开始保存文档,{},{},{}", bizObjectSchemaCode, bizObjectId, attachmentID);
        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        byte[] b_array = new byte[1024];
        InputStream stream = fileToUpload.getInputStream();

        String charset = CharsetUtil.getCharset(stream);

        int i=0;
        while((i=stream.read(b_array, 0, 1024))>0){
            baout.write(b_array, 0, i);
        }
        byte[] contents = baout.toByteArray();

        if (fileToUpload.getOriginalFilename().endsWith(".txt")) {
            contents = new String(contents, charset).getBytes(H3Charset.DEFAULT_CHARSET);
        }
        //文件流
        if(contents != null){
            IEngine engine = this.getEngine();
            User user = engine.getOrganization().GetUserByCode("Administrator");
            Attachment attachment = engine.getBizObjectManager().GetAttachment(user.getObjectID(), bizObjectSchemaCode, bizObjectId, attachmentID);
            if(attachment != null){
                attachment.setContent(contents);
                UserValidator uv = this.getUserValidator();
                String modifiedBy = uv == null ? user.getObjectID() : uv.getUserID();
                //更新文件
                engine.getBizObjectManager().UpdateAttachment(bizObjectSchemaCode, bizObjectId, attachmentID, modifiedBy, attachment.getFileName(), attachment.getContentType(), contents, attachment.getFileFlag());
                LOGGER.info("*************  暂存文档成功   *************");
                return true;
            }
        }else {
            return false;
        }

        return false;
    }



    public byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024*4];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }


    private String GetFileName(String filepath) {
        String filename = null;
        if (filepath != "") {
            String[] names = filepath.split("\\\\");
            filename = names[names.length - 1];
        }
        return filename;
    }

    /**
     *  获取 合同模板的信息
     * @param contractTemplateInstId  合同模板流程id
     * @param bizObjectId   当前表单id
     * @param bizObjectSchemaCode 当前表单 schemaCode
     * @param dataField 当前表单 数据项
     * @param attachmentId 当前表单attachmentId
     * @return  附件信息
     */
    @RequestMapping("/getContractTemplate")
    @ResponseBody
    public Object getContractTemplate(String contractTemplateInstId,String bizObjectId,String bizObjectSchemaCode,String dataField,String attachmentId){

        ResponseResult rst = new ResponseResult(-1L,"",null);
        Date date  = new Date();
        try {
            LOGGER.info("开始获取合同模板文件date={}, contractTemplateInstId={},bizObjectId={},bizObjectSchemaCode={},dataField{}",
                    date.getTime(),  contractTemplateInstId,bizObjectId,bizObjectSchemaCode,dataField);
            InstanceData instanceData =  new InstanceData(getEngine(), contractTemplateInstId, User.AdministratorID);

            List<AttachmentHeader> list = instanceData.getBizObject().GetAttachmentHeaders("contractTemplateUpload", BoolMatchValue.True, null);

            AttachmentHeader header = list.get(0);

            header.getAttachmentID();

            header.getDownloadUrl();
            //合同模板附件
            Attachment attc = instanceData.getBizObject().GetAttachment(header.getAttachmentID());

            //判断是否已存在附件

            Attachment attachment = getEngine().getBizObjectManager().GetAttachment(this.getUserValidator().getUserID(), bizObjectSchemaCode, bizObjectId, attachmentId);
            boolean isadd = false;
            if (attachment == null){
                attachment = new Attachment();
                attachment.setObjectID(UUID.randomUUID().toString());
                attachment.setBizObjectId(bizObjectId);
                attachment.setBizObjectSchemaCode(bizObjectSchemaCode);
                attachment.setDataField(dataField);
                isadd = true;
            }
            attachment.setContent(attc.getContent());
            attachment.setContentType(attc.getContentType());
            attachment.setCreatedTime(date);
            attachment.setCreatedBy(getUserValidator().getUserID());
            attachment.setFileName(attc.getFileName());
            attachment.setLastVersion(true);
            attachment.setModifiedTime(date);
            attachment.setContentLength(attc.getContentLength());

            String result = "";
            if (isadd) {
                result =  getEngine().getBizObjectManager().AddAttachment(attachment);
            }else{
                 getEngine().getBizObjectManager().UpdateAttachment(bizObjectSchemaCode,bizObjectId,
                        attachment.getObjectID(),getUserValidator().getUserID(),
                        attachment.getFileName(),attachment.getContentType(),attachment.getContent(),attachment.getFileFlag());
                result = attachment.getObjectID();
            }


            Map<String, Object> map = new HashMap<>();
            map.put("Code",result);
            map.put("ContentType",attachment.getContentType());
            map.put("Name",attachment.getFileName());
            map.put("Size",attachment.getContentLength());
            map.put("Url",attachment.getDownloadUrl());
            String url = String.format("/Portal/ReadAttachment/Read?BizObjectSchemaCode=%s&BizObjectID=%s&AttachmentID=%s&OpenMethod=0",
                    bizObjectSchemaCode,bizObjectId,result);
            map.put("Url",url);


            rst.setData(new Map[]{map});
            rst.setErrcode(0L);

            LOGGER.info("***合同模板获取保存成功*** date={},result={} " ,date.getTime(), result);

        } catch (Exception e) {
            e.printStackTrace();
            rst.setErrmsg("系统异常");
        }

        return rst;

    }

    /**
     *  保存为 pdf文档
     * @param bizObjectSchemaCode
     * @param bizObjectId
     * @param attachmentID
     * @param fileToUpload
     */
    @RequestMapping(value = "/savePdf", method = RequestMethod.POST)
    @ResponseBody
    public Object savePdf(String bizObjectSchemaCode, String bizObjectId, String attachmentID,@RequestParam("fileToUpload") MultipartFile fileToUpload) {
        LOGGER.info("****************** 开始保存文档,{},{},{}", bizObjectSchemaCode, bizObjectId, attachmentID);
        Map<String, Object> map = new HashMap<>();
        try {
            map.put("code",-1);
            map.put("ret","失败");
            if(fileToUpload != null && fileToUpload.getSize()>0){
                LOGGER.info("fileToUpload info, name={},contentType={},size={}", fileToUpload.getName(), fileToUpload.getContentType(), fileToUpload.getSize());

                IEngine engine = this.getEngine();

                Attachment attachment = engine.getBizObjectManager().GetAttachment(User.AdministratorID, bizObjectSchemaCode, bizObjectId, attachmentID);

                if(attachment != null){
                    attachment.setContent(fileToUpload.getBytes());
                    attachment.setContentType("application/pdf");
                    attachment.setContentLength((int)fileToUpload.getSize());
                    String fileName = attachment.getFileName();
                    fileName =  fileName.substring(0,fileName.lastIndexOf(".")).concat(".pdf");
                    attachment.setFileName(fileName);
                    UserValidator uv = this.getUserValidator();
                    String modifiedBy = uv == null ? User.AdministratorID : uv.getUserID();
                    //更新文件
                    engine.getBizObjectManager().UpdateAttachment(bizObjectSchemaCode, bizObjectId, attachmentID, modifiedBy, attachment.getFileName(), attachment.getContentType(), attachment.getContent(), attachment.getFileFlag());
                    LOGGER.info("************  完成保存pdf文档   **********");
                    map.put("code",0);
                    map.put("ret","成功");
                }
            }

        } catch (Exception e) {
            LOGGER.info(e.getMessage(), e);
        }

        return map;
    }

}